# -*- coding: utf-8 -*-
import logging
from functools import partial
from src.common.pysimplesoap.client import SoapClient
from xml.dom.minidom import CDATASection
from src.utils import util
from etc.config import config

logger = logging.getLogger(__name__)

__author__ = 'raptor'


class Backend(object):
    CLIENT = None
    WSDL = None
    """
    获取患者查询申请单列表
    """

    FUNCTIONS = {
        "RequisitionFind": {"method": "RequisitionFind", "name": "获取患者查询申请单列表",
                            "args": {"SheetID": "", "PatientId": "",
                                     # "args": {"SheetID": "", "ExamID": "", "PatientId": "",
                                     "ScheduleID": "", "PatientDomainId": "", "RequisitionType": "",
                                     "StateType": "", "StateResult": ""}},
        "SyncRequisitionState": {"method": "SyncRequisitionState", "name": "同步申请单状态",
                                 "args": {"SheetID": "", "StateType": "", "StateResult": "",
                                          "OperatorID": "", "OperatorName": "", "OperatorDate": "", "OperatorTime": "",
                                          "Memo": ""}}
    }

    def __init__(self):
        # if Backend.CLIENT is None:
        #     Backend.CLIENT = SoapClient(wsdl=Backend.WSDL, soap_ns="soap", ns="esb", soap_server="no_children_ns",
        #                                 trace=logging.WARNING)
        # self.client = Backend.CLIENT
        Backend.WSDL=config['default'].WSDL
        self.client = SoapClient(wsdl=Backend.WSDL, soap_ns="soap", ns="esb", soap_server="no_children_ns",
                                 trace=logging.WARNING)
        self.funcs = {}
        [self.funcs.__setitem__(k, self.__getattr__(k)) for k in Backend.FUNCTIONS.keys()]

    def __getattr__(self, name):
        try:
            func = Backend.FUNCTIONS[name]
            fn = partial(self._generic_call, func)
            setattr(self, name, fn)
            return fn
        except Exception as e:
            import traceback
            logger.error(traceback.format_exc())
            raise AttributeError('Invalid function name!')

    def _generic_call(self, func, **kwargs):
        """
        调用后端接口，通过SOAP包装的JSON请求和响应
        文档中所说的data['result']不存在
        没有出错的情况下，data就是返回数据
        有错的情况下，data['errMessage']是错误信息
        """
        try:
            args = {k: kwargs.get(k, func['args'].get(k)) for k in func['args'].keys()}
            # key = Decorator.build_key(func['name'], **args)
            body = CDATASection()
            if func["method"] == "RequisitionFind":
                body.data = util.trans_dict_to_xml({"RequisitionFind": util.trans_dict_to_xml(args)})
            elif func['method'] == 'SyncRequisitionState':
                body.data = util.trans_dict_to_xml(
                    {"List": util.trans_dict_to_xml({"RequisitionState": util.trans_dict_to_xml(args)})})
            logger.warning("接口：" + Backend.WSDL)
            logger.warning("参数：" + body.data)
            header = self._get_auth(func["method"])
            logger.warning("Headers：" + str(header))
            # body.data = "<PATIENT_ID>ZY0100012832
            # 08</PATIENT_ID><PATIENT_DOMAIN_ID>2.16.840.1.113883.4.487.2.1.4.4</PATIENT_DOMAIN_ID>"
            req = {"requestHeader": header, "requestBody": body}
            result = self.client.RequestSheet(req=req)
            # result = self.client.query(func['name'], JSON.dumps(args))
            responseHeader = result["RequestSheetResult"].get("responseHeader")
            responseBody = result["RequestSheetResult"].get("responseBody")
            if isinstance(responseHeader, dict) and 'errCode' in responseHeader.keys() and responseHeader.get(
                    "errCode") != "1":
                logger.warning("错误：没有数据：" + str(responseHeader))
                return 501, "没有数据"
            else:
                # logger.warning("有数据responseBody：" + str(responseBody))
                data = util.trans_xml_to_dict(responseBody)
                logger.warning("转换成dict后的数据：" + str(data))
                return 200, data
            logger.warning("未知错误：" + str(responseHeader))
            return 400, responseHeader.get('errMessage', "未知错误")
        except Exception as e:
            logger.warning("接口错误：" + str(e))
            raise

    def _get_auth(self, method):
        headers = {}
        headers['sender'] = "2.16.840.1.113883.4.487.2.1.5"
        headers['receiver'] = "2.16.840.1.113883.4.487.2.1.3"
        headers['requestTime'] = util.now_format_no()
        headers['msgType'] = method
        headers['msgId'] = "SPEC" + util.now_format_no()
        headers['msgPriority'] = "Normal"
        headers['msgVersion'] = "1.0.0"
        return headers

    def set_backend_static_urls(self, web_service):
        """
        获得url
        :param webSrv:
        """
        maps = web_service.url_map._rules
        urls = list()
        for m in maps:
            name = m.endpoint.split(".")
            if len(name) > 1:
                l = {"method_name": name[1], "url": m.rule}
                urls.append(l)
        Backend.URLS = urls

    def get_function_method_by_name(self, name):
        for k in self.FUNCTIONS:
            if "name" in self.FUNCTIONS[k] and self.FUNCTIONS[k]["name"] == name:
                return k
